#include <linux/module.h>
#include <linux/uaccess.h> //copy_to/from_user
#include <linux/device.h>
#include <linux/fs.h>

#include "led_opr.h"

#define LED_NUM 2

/* 1、主设备号为0，内核自动分配 */
static int major = 0;
static struct class *led_class;
struct led_operations *p_led_opr;

#define MIN(a, b) (a < b ? a : b)

void led_device_create(int minor)
{
	device_create(led_class, NULL, MKDEV(major, minor), NULL, "rlk3399_led%d", minor);
}

void led_device_destory(int minor)
{
	device_destroy(led_class, MKDEV(major, minor));
}

void register_led_operation(struct led_operations *opr)
{
	p_led_opr = opr;
}
EXPORT_SYMBOL(led_device_create);

EXPORT_SYMBOL(led_device_destory);

EXPORT_SYMBOL(register_led_operation);

/* 3、实现对应的open/read/write 等函数，填入file_operation结构体*/
ssize_t led_drv_read (struct file *file, char __user *buf, size_t size, loff_t *offset)
{
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	return 0;
}

ssize_t led_drv_write (struct file *file, const char __user *buf, size_t size, loff_t *offset)
{
    int err;	
	char status;
	struct inode *inode = file_inode(file);
	int minor = iminor(inode);
	
    printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	err = copy_from_user(&status, buf, 1);

	/* 根据次设备号和status控制LED */
	p_led_opr->ctl(minor, status);
	
	return 1;
}

int led_drv_open (struct inode *node, struct file *file)
{
	int minor = iminor(node);
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	
	/* 根据次设备号初始化LED */
	p_led_opr->init(minor);
	
	return 0;
}

int led_drv_close (struct inode *node, struct file *file)
{
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	return 0;
}

/* 2、 定义自己的file_operations 结构体 */
static struct file_operations led_fops = {
	.owner = THIS_MODULE,
	.open = led_drv_open,
	.read = led_drv_read,
	.write = led_drv_write,
	.release = led_drv_close,
};

/* 入口函数 __init:段属性（用一次，然后释放）*/
static int __init led_init(void)
{
	int err;
	int i;
	
	printk("led drv init\n");

	/* 注册字符设备 */
	major = register_chrdev(major, "100ask_led", &led_fops);	/* dev/100ask_led */

	led_class = class_create(THIS_MODULE, "100ask_led_class");
	err = PTR_ERR(led_class);
	if (IS_ERR(led_class)) {
		printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
		unregister_chrdev(major, "led");
		return -1;
	}
	
	return 0; 
}

/* 出口函数 __exit:段属性，此段不会链接进内核（驱动被编进内核无需释放无需出口，出口函数无存在必要）*/
static void __exit led_exit(void)
{
	int i;
	printk("led drv exit\n");

	for (i = 0; i < LED_NUM; i++)
		
	
	class_destroy(led_class);
	unregister_chrdev(major, "led_drv");
}
module_init(led_init);
module_exit(led_exit);

MODULE_LICENSE("GPL");

